Domainmapping bring your own certificate#11250
Domainmapping bring your own certificate#11250knative-prow-robot merged 19 commits intoknative:mainfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## main #11250 +/- ##
==========================================
+ Coverage 87.70% 87.71% +0.01%
==========================================
Files 191 191
Lines 9246 9256 +10
==========================================
+ Hits 8109 8119 +10
Misses 882 882
Partials 255 255
Continue to review full report at Codecov.
|
julz
left a comment
There was a problem hiding this comment.
This looks good, thanks! 🎉 I mostly just have a little bike-shed about the field name :).
I guess (probably in a follow up, no need for it to be done in this PR, as far as I'm concerned) we will want to relax the check in the reconciler to allow tls even with autoTLS disabled as long as (and only as long as!) the secret is provided explicitly.
| // If defined it will use the existing tls secret with the given name, otherwise it will attempt to create | ||
| // a new secret with the expected name to be used by the certificate. | ||
| // +optional | ||
| TLSSecret string `json:"tlsSecret,omitempty"` |
There was a problem hiding this comment.
What do you think about having this roughly match the similar section in K8s Ingress? (Mostly just for consistency/familiarity). That would also line up with (Knative) IngressTLS which has secretName.
i.e.
tls:
secretName: ..
There was a problem hiding this comment.
@julz I've addressed your comments please let me know if everything looks good to you
c8517ae to
6a26305
Compare
4e8d58c to
082a31e
Compare
|
/retest |
|
/assign @dprotaso |
|
|
||
| func (r *Reconciler) tls(ctx context.Context, dm *v1alpha1.DomainMapping) ([]netv1alpha1.IngressTLS, []netv1alpha1.HTTP01Challenge, error) { | ||
| if !autoTLSEnabled(ctx, dm) { | ||
| if !autoTLSEnabled(ctx, dm) && dm.Spec.TLS == nil { |
There was a problem hiding this comment.
I'd actually land this line in a follow-on PR I think: we want to think through the cases here (eg if autotls is not enabled and spec.TLS is non-nil but SecretName is empty what should happen? Should we error out if the cert doesn't exist but autotls is disabled?) and probably add some test coverage.
| type SecretTLS struct { | ||
| // SecretName is the name of a TLS secret. | ||
| // | ||
| // Either a existing secret in the cluster or the new secret to be created. |
There was a problem hiding this comment.
| // Either a existing secret in the cluster or the new secret to be created. | |
| // Either an existing secret in the cluster or the new secret to be created. |
| Spec: networkingv1alpha1.CertificateSpec{ | ||
| DNSNames: []string{dnsName}, | ||
| SecretName: certName, | ||
| SecretName: secretName, |
There was a problem hiding this comment.
The godoc for this says
SecretName is the name of the secret resource to store the SSL certificate in.
It's not obvious whether different controllers will check this secret and not overwrite it. Even if it does not what happens when the certificate in the secret expires?
I wonder if when we bring your own certificate we don't use the default certificate class.
There was a problem hiding this comment.
I wonder if when we bring your own certificate we don't use the default certificate class.
I guess we still need something to set the certificate as 'ready`
There was a problem hiding this comment.
At least in net-http01 I see it checks for the secret before trying to create it here which is consistent with what I've tested, this also happens with cert-manager but I haven't found the specific code that does this in cert-manager. I'm not sure if this answers your question
There was a problem hiding this comment.
net-http01 may be work well but we can't assume other's won't
ie. cert manager
The secret name is delegated to a cert manager CRD here. A rough scan looks like there are edge cases where it might fail
Specifically the secret is evaluated against the following policy chain to determine whether to re-issue the certificate
Two concerning assertions are:
SecretPrivateKeyMatchesSpec
When creating the cert manager crd we don't indicate the private key type. When it's not set cert manager assumes we're bringing a RSA private key. Thus if we brought a ECDSA cert then I think it trigger a reissue that'll fail/overwrite our secret
SecretIssuerAnnotationsNotUpToDate
it seems like the secret needs the 'correct' annotations or it'll be re-issued - these annotations are cert manager specific.
b48d735 to
e4b5958
Compare
|
/retest |
|
Can we add an e2e test? |
docs/serving-api.md
Outdated
| <td> | ||
| <em>(Optional)</em> | ||
| <p>TLS indicates the existing or expected tls secret that should be used for certificate generation.</p> | ||
| <p>If defined it will use the existing tls secret with the given name, otherwise it will attempt to create |
There was a problem hiding this comment.
same comment as below
docs/serving-api.md
Outdated
| <td> | ||
| <em>(Optional)</em> | ||
| <p>TLS indicates the existing or expected tls secret that should be used for certificate generation.</p> | ||
| <p>If defined it will use the existing tls secret with the given name, otherwise it will attempt to create |
There was a problem hiding this comment.
same comment as below
| // TLS indicates the existing or expected tls secret that should be used for certificate generation. | ||
| // | ||
| // If defined it will use the existing tls secret with the given name, otherwise it will attempt to create | ||
| // a new secret with the expected name to be used by the certificate. |
There was a problem hiding this comment.
Is this still true ? As in will a new secret be created if one doesnt exist ?
There was a problem hiding this comment.
Might also want to update the description in the PR and original issue if the requirements have changed as we explicitly don't want to create a secret if it doesn't exist
5acb2a9 to
670109a
Compare
| // SecretName is the name of a TLS secret. | ||
| // | ||
| // An existing tls secret. | ||
| SecretName string `json:"secretName"` |
There was a problem hiding this comment.
| // SecretName is the name of a TLS secret. | |
| // | |
| // An existing tls secret. | |
| SecretName string `json:"secretName"` | |
| // SecretName is the name of the existing secret used to terminate TLS traffic. | |
| SecretName string `json:"secretName"` | |
| // SecretNamespace is the namespace of the existing TLS secret. | ||
| // | ||
| // Namespace of the existing secret, if missing the namespace of the domainmapping is assumed. |
There was a problem hiding this comment.
| // SecretNamespace is the namespace of the existing TLS secret. | |
| // | |
| // Namespace of the existing secret, if missing the namespace of the domainmapping is assumed. | |
| // SecretNamespace is the namespace of the existing secret used to terminate SSL traffic. If empty the namespace of the DomainMapping is assumed. |
| // TLS indicates the existing tls secret that should be used for this domain. | ||
| // | ||
| // If defined it will use the tls secret with the given name assumed to exist | ||
| // in the same namespace as the domainmapping. |
There was a problem hiding this comment.
| // TLS indicates the existing tls secret that should be used for this domain. | |
| // | |
| // If defined it will use the tls secret with the given name assumed to exist | |
| // in the same namespace as the domainmapping. | |
| // TLS allows the DomainMapping to terminate TLS traffic with an existing secret. |
| if dm.Spec.TLS != nil { | ||
| namespace := dm.Namespace | ||
| if dm.Spec.TLS.SecretNamespace != "" { | ||
| namespace = dm.Spec.TLS.SecretNamespace | ||
| } | ||
| return []netv1alpha1.IngressTLS{ | ||
| { | ||
| Hosts: []string{dm.Name}, | ||
| SecretName: dm.Spec.TLS.SecretName, | ||
| SecretNamespace: namespace, | ||
| }, | ||
| }, nil, nil | ||
| } | ||
|
|
There was a problem hiding this comment.
Can you add a unit test for this as well?
| }, metav1.CreateOptions{}) | ||
|
|
||
| if err != nil { | ||
| t.Fatalf("Domainmapping creation could not be completed: %v", err) |
There was a problem hiding this comment.
nit: update this message to say the secret failed to create
| Status: v1alpha1.DomainMappingStatus{}, | ||
| } | ||
|
|
||
| t.Log("HOST===>", host) |
There was a problem hiding this comment.
unsure if this was for debugging - can we change the message to be a clear sentence or drop it?
| t.Log("HOST===>", host) | ||
| _, err = clients.ServingAlphaClient.DomainMappings.Create(context.Background(), &dm, metav1.CreateOptions{}) | ||
| if err != nil { | ||
| t.Fatalf("Problem creating domainmapping : %v", err) |
There was a problem hiding this comment.
Let's print the host here
| t.Fatalf("Problem creating domainmapping : %v", err) | |
| t.Fatalf("Problem creating DomainMapping %q: %v", host, err) |
| if waitErr := wait.PollImmediate(test.PollInterval, test.PollTimeout, func() (bool, error) { | ||
| ingresses, err := clients.NetworkingClient.Ingresses.Get(context.Background(), ksvc.Service.Name, metav1.GetOptions{}) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| for _, cond := range ingresses.Status.Conditions { | ||
| if cond.Type == apis.ConditionReady { | ||
| return cond.IsTrue(), nil | ||
| } | ||
| } | ||
| return false, nil | ||
| }); waitErr != nil { | ||
| t.Fatalf("Ingresses %s never became ready: %v", ksvc.Service.Name, waitErr) | ||
| } | ||
|
|
||
| err = shared.CheckDistribution(context.Background(), t, clients, | ||
| &url.URL{ | ||
| Host: host, | ||
| Scheme: "HTTPS", | ||
| }, 1, 1, []string{test.PizzaPlanetText1}, resolvableCustomDomain) | ||
| if err != nil { | ||
| t.Fatalf("Hitting %v didn't return the expected response: %v", dm.Name, err) | ||
| } |
There was a problem hiding this comment.
The Kingress is sorta an implementation detail of the DomainMapping - we should be checking the Ready condition on the DomainMapping itself
I also wonder if we CheckDistribution isn't needed and maybe we could just use WaitForEndpointState
56aac5f to
b14642a
Compare
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
allow domainmappings to specify the tls secret to be used by the autoTLS certificate Signed-off-by: Fabian Lopez <lfabian@vmware.com> Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com> Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Co-authored-by: Bishoy Youssef <byoussef@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com> Co-authored-by: Sameer Vohra <vsameer@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
90ab26a to
ba2fd25
Compare
|
/approve 🎉 leaving lgtm to @julz |
julz
left a comment
There was a problem hiding this comment.
Awesome stuff, thanks! Couple little indentation nits and then it'll lgtm 🔥
| return []netv1alpha1.IngressTLS{ | ||
| { | ||
| Hosts: []string{dm.Name}, | ||
| SecretName: dm.Spec.TLS.SecretName, | ||
| SecretNamespace: dm.Namespace, | ||
| }, | ||
| }, nil, nil | ||
| } |
There was a problem hiding this comment.
indentation nit:
| return []netv1alpha1.IngressTLS{ | |
| { | |
| Hosts: []string{dm.Name}, | |
| SecretName: dm.Spec.TLS.SecretName, | |
| SecretNamespace: dm.Namespace, | |
| }, | |
| }, nil, nil | |
| } | |
| return []netv1alpha1.IngressTLS{{ | |
| Hosts: []string{dm.Name}, | |
| SecretName: dm.Spec.TLS.SecretName, | |
| SecretNamespace: dm.Namespace, | |
| }}, nil, nil | |
| } |
test/e2e/domain_mapping_test.go
Outdated
| } | ||
|
|
||
| host := ksvc.Service.Name + ".example.org" | ||
| // set resolvabledomain for custom domain to false by default. |
There was a problem hiding this comment.
nit: not sure this comment really adds anything the code it's describing doesn't say more clearly, I'd probably just drop it
test/e2e/domain_mapping_test.go
Outdated
| Name: ksvc.Service.Name, | ||
| Namespace: ksvc.Service.Namespace, | ||
| Kind: "Service", | ||
| }, TLS: &v1alpha1.SecretTLS{ |
There was a problem hiding this comment.
| }, TLS: &v1alpha1.SecretTLS{ | |
| }, | |
| TLS: &v1alpha1.SecretTLS{ |
test/e2e/domain_mapping_test.go
Outdated
|
|
||
| // service to be mapped |
There was a problem hiding this comment.
I'd be tempted to drop this comment since it doesn't really add anything, but if we keep it let's capitalise it and add a period just to be consistent with most of the rest of the code in serving.
| // service to be mapped | |
| // Create service to be mapped. |
Signed-off-by: Fabian Lopez <lfabian@vmware.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dprotaso, julz, shinigambit The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
@shinigambit: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
|
/retest |
|
It seems no documentation is available yet. I opened knative/docs#4081 to track for the new docs. |
Allow domainmappings to specify the tls secret to be used by the autoTLS
certificate
These changes assume that autoTLS is enabled in the cluster and that if the secret doesn't exist in the cluster the intent
is to create a new secret with the given name
Fixes #10530
Release Note